#include "stringex.h"
#include <stdarg.h>
#include "os/mutex.h"
#include "os/mutexlocker.h"

#define FORMAT_BUF_MAX 128

//减少栈的使用
static Mutex m_formatBufMutex;
static char formatBuf[FORMAT_BUF_MAX];

std::string StringEx::Format(const char* format, ...)
{
    MutexLocker locker(&m_formatBufMutex);

    va_list argList;

    va_start(argList, format);
    vsnprintf(formatBuf, FORMAT_BUF_MAX, format, argList);
    va_end(argList);
        
    return std::string(formatBuf);
}

bool StringEx::IsEmptyOrWhiteSpace(const std::string& str)
{
    if (str.empty())
        return true;

    for (auto& c : str)
    {
        if (c != ' ')
            return false;
    }

    return true;
}

std::string &StringEx::Trim(std::string &str)
{
    if (str.empty())   
    {  
        return str;  
    }  
  
    str.erase(0, str.find_first_not_of(" "));  
    str.erase(str.find_last_not_of(" ") + 1);  
    return str;  
}

std::vector<std::string> StringEx::Split(const std::string &str, const std::string &delim, bool removeEmpty, bool trim)
{
    if (str.empty())
    {
        return std::vector<std::string>();
    }

    std::vector<std::string> vect;
    auto lastPos = str.find_first_not_of(delim, 0);
    auto pos = str.find_first_of(delim, lastPos);
    while (std::string::npos != pos || std::string::npos != lastPos) 
    {
        auto line = str.substr(lastPos, pos - lastPos);
        
        if(trim)
            Trim(line);
        if (removeEmpty)
        {
            if (!IsEmptyOrWhiteSpace(line))
                vect.push_back(std::move(line));
        }
        else
        {
            vect.push_back(std::move(line));
        }

        lastPos = str.find_first_not_of(delim, pos);
        pos = str.find_first_of(delim, lastPos);
    }

    return vect;
}

template<typename TC>
static std::string __JoinImpl(TC strs, const std::string &delim)
{
    std::string result;
    
    if(strs.size() == 0) 
        return result;

    int index = 0;
    for(auto it = strs.begin(); it != strs.end(); it++)
    {
        result.append(*it);

        index++;
        if(index < strs.size())
        {
            result.append(delim);
        }
    }

    return result;
}

std::string StringEx::Join(const std::list<std::string> &strs, const std::string &delim)
{
    return __JoinImpl(strs, delim);
}

std::string StringEx::Join(const std::vector<std::string> &strs, const std::string &delim)
{
    return __JoinImpl(strs, delim);
}
